/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.refunite.mobile.s60.util;

import org.refunite.mobile.s60.exception.TechnicalException;
import org.refunite.mobile.s60.persistence.PersistenceStoreProvider;
import org.refunite.mobile.s60.widget.AbstractFormWidget;
import org.refunite.mobile.s60.widget.WidgetFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Vector;
import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.services.transport.payload.ByteArrayPayload;
import org.javarosa.form.api.FormEntryController;
import org.javarosa.form.api.FormEntryModel;
import org.javarosa.form.api.FormEntryPrompt;
import org.javarosa.model.xform.XFormSerializingVisitor;
import org.javarosa.xform.util.XFormUtils;

/**
 *
 * @author I040022
 */
public class FormController {
    private static FormDef formDef;
    private static FormEntryModel formEntryModel;
    private static FormEntryController formEntryController;

    private static Vector stepVector;

    private static int currentStep;

    private static FormController formControllerInstance;
    public FormController(){
        setupFormDefinition();
    }

    public static void loadUpdatedForm(FormDef newFormDef){
        formDef = newFormDef;
        initForm();
    }
    public static FormController getInstance(){
        if(formControllerInstance == null){
            formControllerInstance = new FormController();
            initForm();
        }
        return formControllerInstance;
    }

    public static void initForm(){
        formEntryModel = new FormEntryModel(formDef);
        formEntryController = new FormEntryController(formEntryModel);
        formEntryModel.getForm().initialize(true);
    }
    public static void generateSteps(){
        stepVector = new Vector();
        int numOfQuestions = formEntryModel.getNumQuestions();
        for(int i = 0; i<numOfQuestions; i++){
            int eventType = formEntryController.stepToNextEvent();
            if(formEntryController.EVENT_QUESTION == eventType){
                FormEntryPrompt fep = formEntryModel.getCurrentQuestionPrompt();
                if(fep.getDataType() != Constants.DATATYPE_BARCODE){
                    AbstractFormWidget form = WidgetFactory.createUIItem(formEntryController, fep, i);
                    stepVector.addElement(form);
                }
            }
        }
        stepVector.trimToSize();
        currentStep = 0;
    }

    public static void saveCompleteForm(){
        try{
            /*
            String path = System.getProperty("fileconn.dir.private");
            System.out.println("Private folder:"+path+"log"+System.currentTimeMillis()+".txt");
            FileConnection fileConnection = (FileConnection) Connector.open(path+"log.txt",Connector.READ_WRITE);
            if(!fileConnection.exists()){
                fileConnection.create();
            }
             *
            DataOutputStream dos = fileConnection.openDataOutputStream();
             */
            ByteArrayPayload payload;

            // assume no binary data inside the model.
            FormInstance datamodel = formEntryController.getModel().getForm().getInstance();
            XFormSerializingVisitor serializer = new XFormSerializingVisitor();
            payload = (ByteArrayPayload) serializer.createSerializedPayload(datamodel);
            InputStream is = payload.getPayloadStream();
            int streamLength = is.available();
            byte[] content = new byte[streamLength];
            is.read(content);
            is.close();
            PersistenceStoreProvider.saveCompletedRegistrationForm(new String(content).trim());
/*
            payload.writeExternal(dos);
            dos.close();
 */
        }catch(Exception e){
            e.printStackTrace();
        }

    }

    public static int getNumOfSteps(){
        return stepVector.size();
    }
    public static AbstractFormWidget getCurrentStep(){
        return (AbstractFormWidget)stepVector.elementAt(currentStep);
    }

    public static AbstractFormWidget getNextStep(){
        if(currentStep + 1 == stepVector.size()){
           return null;
        }else{
            currentStep++;
            return getCurrentStep();
        }
    }

    public static AbstractFormWidget getPreviousStep(){
        if(currentStep != 0){
            currentStep--;
        }
        return getCurrentStep();
    }

    private void setupFormDefinition(){
        try{
            String formContentString = PersistenceStoreProvider.readFormContent();
            byte[] formContent = null;
            if(formContentString == null){
                formContent = initFormContent();
            }else{
                formContent = formContentString.trim().getBytes("UTF-8");
            }
            ByteArrayInputStream bais = new ByteArrayInputStream(formContent);
            formDef = XFormUtils.getFormFromInputStream(bais);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private byte[] initFormContent() throws TechnicalException{
        try{
            InputStream is = this.getClass().getResourceAsStream("/registration.xml");
            // registration form doesn't exist, get original from jar
            byte[] temp = new byte[is.available()];
            StringBuffer buff = new StringBuffer();
            
            while(is.read(temp) != -1){
                buff.append(new String(temp, "UTF-8"));
            }
            is.close();
            PersistenceStoreProvider.updateFormContent(buff.toString());
            return buff.toString().getBytes("UTF-8");
        }catch(Exception e){
            throw new TechnicalException(e);
        }

    }

    public static String[] getAvailableLanguages(){
        return formEntryModel.getLanguages();
    }

    public static String getUsedLanguage(){
        return formEntryModel.getCurrentLanguage();
    }

    public static void setUsedLanguage(String language){
        formEntryController.setLanguage(language);
    }

    public static int getCurrentStepIndex(){
        return currentStep;
    }
}
